package com.atguigu.tingshu.common.aspect;

import com.alibaba.nacos.common.utils.StringUtils;
import com.atguigu.tingshu.common.annotation.Login;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
public class LoginAspect {
    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Around("@annotation(login)")
    public Object loginAspect(ProceedingJoinPoint joinPoint, Login login) throws Throwable {
        //获取请求对象 并强转为ServletRequestAttributes 对象
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        //获取request对象
        assert servletRequestAttributes != null;
        HttpServletRequest request = servletRequestAttributes.getRequest();
        //获取请求头中的token
        String token = request.getHeader("token");

        UserInfoVo userInfoVo = null;
        //如果token存在，则根据token获取用户信息
        if (StringUtils.isNotBlank(token)) {
            userInfoVo = (UserInfoVo) redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX + token);
            if (userInfoVo != null) {
                //将用户信息保存到本地线程的
                AuthContextHolder.setUserId(userInfoVo.getId());
                AuthContextHolder.setUsername(userInfoVo.getNickname());
            }
        }
        //判断是否需要登录
        if (login.required() && userInfoVo == null) {
            throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
        }
        //执行方法
        Object result = joinPoint.proceed();
        //移除本地线程中的用户信息
        AuthContextHolder.removeUserId();
        AuthContextHolder.removeUsername();
        //返回结果
        return result;
    }
}
